// Author; Gonzalo Luzardo M.
// Contact: gonchalox@gmail.com, gluzardo@espol.edu.ec


import java.awt.image.BufferedImage; 
import java.util.HashSet;
import java.util.Iterator;
import processing.core.*;

public class DelaunayTriangulationCreator {

	public int m_edge_pixels;
	private int m_random_generated_points;
		
	private int m_width;
	private int m_height;
	BufferedImage m_edge_buffer;
	private PApplet m_applet;
	private PImage m_faces_image;
	
	private int m_initial_triangle_size;

	
	//Delaunay 
	private Delaunay m_delaunay;
	
	//Edge detector
	private CannyEdgeDetector m_edge_detector;
	
	//Points
	private HashSet<Point> m_points;
			
	//Constructor
	public DelaunayTriangulationCreator(PApplet applet, int width, int height, int edge_pixels, int random_pixels){
		m_applet = applet;
		m_width = width;
		m_height = height;

		//Initialize images
		m_faces_image = m_applet.createImage(m_width,m_height,PApplet.RGB);
		
		//Initial triangle size
		m_initial_triangle_size = 10000;
		//Edges and Generated points
		m_edge_pixels = edge_pixels;
		m_random_generated_points = random_pixels;
		
		//Edge detector
		m_edge_detector = new CannyEdgeDetector();
		m_edge_detector.setLowThreshold(0.5f);
		m_edge_detector.setHighThreshold(1f);
		
		//Points
		m_points = new HashSet<Point>();
	}
	
	//Get mosaic
	public void process(PImage image, int xi, int yi, int xf, int yf){
				
		//1. Resize image to fit edge image
		m_faces_image.copy(image,xi,yi,xf-xi,yf-yi,0,0,m_width,m_height);
						
		//2. Getting points from edge detection
		//Edge detection
		System.out.println("\nMaking edge detection...");
		System.out.println("Xi:"+xi+" Yi:"+yi+" Xf:"+xf+" Yf:"+yf);
		System.out.println("W:" + (xf-xi) + " H:" + (yf-yi));
		BufferedImage faces_image = new BufferedImage(m_width,m_height,BufferedImage.TYPE_INT_RGB);
		faces_image.setRGB(0,0,m_faces_image.width,m_faces_image.height,m_faces_image.pixels, 0,m_faces_image.width);
		m_edge_detector.setSourceImage(faces_image);
		System.out.println("Starting edge detector...");
		m_edge_detector.process();
		System.out.println("Finalize edge detector...");
		//End edge detection
 		
		//m_triangles creation
		System.out.println("Starting Delaunay triangulation..");
		m_points.clear();
		m_points = m_edge_detector.getPoints(m_edge_pixels);
		
		System.out.println("Point in edge obtained:" + m_points.size());
		m_delaunay = new Delaunay(new Point(0, m_initial_triangle_size), 
							         new Point(m_initial_triangle_size,-m_initial_triangle_size), 
							         new Point(-m_initial_triangle_size,-m_initial_triangle_size), 
							         10*100);
		
		Iterator<Point> it = m_points.iterator();
		
		System.out.println("Starting edge triangulation..");
		while (it.hasNext()) {
			Point tmp = it.next();
			tmp.setY(-tmp.getY());
			m_delaunay.insertarVertice3(tmp);
		}
		System.out.println("Finalize edge triangulation..");
		
		//3. Getting rest of points 
		System.out.println("Starting random triangulation with:" +  m_random_generated_points + " points");
		for (int i = 0; i < m_random_generated_points; i++) {
			int x = (int) (Math.random() * m_width);
			int y = (int) (Math.random() * m_height);
			Point tmp = new Point(x, -y);
			m_points.add(tmp);
			m_delaunay.insertarVertice3(tmp);
		}
		System.out.println("Finalize random triangulation");
		System.out.println("Finalize Delaunay triangulation..");
		System.out.println("Total points used: " + m_delaunay.getPoints().size());
	}

	//Return delaunay object
	public Delaunay getDelaunay(){
		return m_delaunay;
	}

	//Get Faces Images
	public PImage getFacesImages(){
		return m_faces_image;
	}
}
